package com.xsf.pay.common.utils;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.xsf.pay.common.annotation.Convert;
import com.xsf.pay.common.enums.ConvertType;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;

/**
 * @author xujianfeng
 * 只支持同类型数据转换 如 string -> string
 */
@Slf4j
public class ConvertUtils {

    private static final Map<ConvertType, Function<String, String>> ACTION_MAP = init();

    public static <T> void fieldValSetList(List<T> dataList) {
        if (CollUtil.isEmpty(dataList)) {
            return;
        }
        dataList.forEach(ConvertUtils::setValue);
    }

    public static <T> void fieldValSet(T t) {
        if (ObjectUtil.isEmpty(t)) {
            return;
        }
        setValue(t);
    }

    private static <T> void setValue(T t) {
        Class<?> clazz = t.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            //获取父类字段
            clazz = clazz.getSuperclass();
        }
        for (Field field : fieldList) {
            Convert convert = field.getAnnotation(Convert.class);
            if (convert == null) {
                continue;
            }
            try {
                field.setAccessible(true);
                Object origVal = field.get(t);
                if (origVal instanceof String) {
                    String var = origVal.toString();
                    if (ACTION_MAP.containsKey(convert.type())) {
                        field.set(t, ACTION_MAP.get(convert.type()).apply(var));
                    }         // 日期格式化
                    else if (ConvertType.DATE_FORMAT.equals(convert.type())) {
                        if (StrUtil.isBlank(convert.format())) {
                            field.set(t, DateUtil.format(DateUtil.parse(var), DatePattern.NORM_DATETIME_PATTERN));
                        } else {
                            field.set(t, DateUtil.format(DateUtil.parse(var), convert.format()));
                        }
                    }
                }
                if (origVal instanceof BigDecimal) {
                    String var = origVal.toString();
                    if (ACTION_MAP.containsKey(convert.type())) {
                        field.set(t, new BigDecimal(ACTION_MAP.get(convert.type()).apply(var)));
                    }
                }
                if (origVal instanceof Long) {
                    String var = origVal.toString();
                    if (ACTION_MAP.containsKey(convert.type())) {
                        field.set(t, Long.parseLong(ACTION_MAP.get(convert.type()).apply(var)));
                    }
                }
            } catch (IllegalAccessException e) {
               log.error("执行参数转换错误", e);

            }
        }

    }

    private static Map<ConvertType, Function<String, String>> init() {
        Map<ConvertType, Function<String, String>> map = new EnumMap<>(ConvertType.class);
        map.put(ConvertType.RATE_TO_STRING, StringUtils::convertRateToString);
        map.put(ConvertType.STRING_TO_RATE, StringUtils::convertStringToRate);
        map.put(ConvertType.YUAN_TO_FEN, StringUtils::yuanToFen);
        map.put(ConvertType.FEN_TO_YUAN, StringUtils::fenToYuan);
        map.put(ConvertType.NEGATIVE_FEN_TO_YUAN, StringUtils::negativeFenToYuan);
        map.put(ConvertType.PERCENT, StringUtils::percent);
        map.put(ConvertType.NOT_NULL, StringUtils::notNull);
        map.put(ConvertType.NOT_PERCENT_SIGN, StringUtils::notPercentSign);
        return map;
    }

}
